﻿#ifndef JSQLTABLEMGR_H
#define JSQLTABLEMGR_H

#include "jsql_global.h"
#include <QStringList>
#include <QPointF>
#include "jsqlcustomtype.h"

// - class JSqlTableMgr -

class JSqlTableMgrPrivate;
class QSqlDatabase;

class JSQL_EXPORT JSqlTableMgr
{
public:
    /**
     * @brief isValid, 查询数据库表管理器是否有效
     * @return, true：可用；false：不可用
     */
    bool isValid() const;

    /**
     * @brief transaction
     * @return
     */
    bool transaction();

    /**
     * @brief commit
     * @return
     */
    bool commit();

    /**
     * @brief rollback
     * @return
     */
    bool rollback();

    /**
     * @brief databaseName
     * @return
     */
    QString databaseName() const;

    /**
     * @brief loadConfig, 加载配置文件，并打开初始化数据库
     * @param filePath, 配置文件路径
     * @return, true：加载成功；false：加载失败
     */
    bool loadConfig(const QString &filePath);

    /// table operation

    /**
     * @brief existsTable, 查询指定表名是否存在于数据库中
     * @param tableName, 表名
     * @return, true：存在；false：不存在
     */
    bool existsTable(const QString &tableName) const;

    /**
     * @brief tableColumns, 获取指定表的所有列名称
     * @param tableName, 表名
     * @return, 列名称列表
     */
    QStringList tableColumns(const QString &tableName) const;

    /**
     * @brief createMainTable, 创建主表
     * @return, true：创建成功；false：创建失败
     */
    bool createMainTable();

    /**
     * @brief createSignalTable, 创建信号表
     * @param tableName, 表名
     * @return, true：创建成功；false：创建失败
     */
    bool createSignalTable(const QString &tableName);

    /**
     * @brief createRecordTable, 创建数据记录表
     * @param tableName, 表名
     * @param columnNames, 列名
     * @return, true：创建成功；false：创建失败
     */
    bool createRecordTable(const QString &tableName, const QStringList &columnNames);

    /**
     * @brief createHotSpotTable, 创建信热点范围表
     * @param tableName, 表名
     * @return, true：创建成功；false：创建失败
     */
    bool createHotSpotTable(const QString &tableName);

    /**
     * @brief rowCountOfTable
     * @param tableName
     * @return
     */
    int rowCountOfTable(const QString &tableName);

    /**
     * @brief addRecordSymbol, 向数据表添加信号量
     * @param tableName, 表名
     * @param symbols, 信号名
     * @return, true：添加成功；false：添加失败
     */
    bool addRecordSymbol(const QString &tableName, const QStringList &symbols);

    /**
     * @brief removeRecordSymbol, 从数据表中删除信号量
     * @param tableName, 表名
     * @param symbols, 信号名
     * @return, true：删除成功；false：删除失败
     */
    bool removeRecordSymbol(const QString &tableName, const QStringList &symbols);

    /**
     * @brief updateRecordSymbol, 更新数据表信号量（丢掉旧的信号量，使用新的信号量）
     * @param tableName, 表名
     * @param symbols, 信号名
     * @param isIgnoreSift, true：忽略筛选；false：不忽略筛选
     * @return, true：更新成功；false：更新失败
     */
    bool updateRecordSymbol(const QString &tableName, const QStringList &symbols,
                            bool isIgnoreSift);

    /// drop tables or truncate data

    /**
     * @brief clearDatabase, 清空数据库中的所有数据[保留主表]
     * @return, true：清除成功；false：清除失败
     */
    bool clearDatabase();

    /**
     * @brief clearTable, 清空指定表的数据
     * @param tableName, 表名
     * @return, true：清除成功；false：清除失败
     */
    bool clearTable(const QString &tableName);

    /**
     * @brief deleteTable, 删除指定表
     * @param tableName, 表名
     * @return, true：删除成功；false：删除失败
     */
    bool deleteTable(const QString &tableName);

    /**
     * @brief renameTable, 重命名表名
     * @param tableName, 原有表名称
     * @param newTableName, 新的表名称
     * @return, true：重命名成功；false：重命名失败
     */
    bool renameTable(const QString &tableName, const QString &newTableName);

    /**
     * @brief open, 打开数据库
     * @return, true：打开成功；false：打开失败
     */
    bool open();

    /**
     * @brief close, 关闭数据库
     */
    void close();

    /**
     * @brief databaseType, 获取数据库类型名称
     * @return, 数据库类型名称
     */
    QString databaseType() const;

    /**
     * @brief connectionName, 获取数据库链接名称
     * @return, 数据库链接名称
     */
    QString connectionName() const;

    /**
     * @brief mainTableName, 获取主表名称
     * @return, 主表名称
     */
    static QString mainTableName();

    /**
     * @brief signalTableNamePrefix, 获取信号表名称固定前缀
     * @return, 信号表名称前缀
     */
    static QString signalTableNamePrefix();

    /**
     * @brief recordTableNamePrefix, 获取值表名称固定前缀
     * @return, 值表名称前缀
     */
    static QString recordTableNamePrefix();

    /**
     * @brief hotSpotTableNamePrefix, 获取热点范围表名称固定前缀
     * @return, 值表名称前缀
     */
    static QString hotSpotTableNamePrefix();

    /**
     * @brief suffixOfSubTable
     * @param tableName
     * @return
     */
    static QString suffixOfSubTable(const QString &tableName);

    /**
     * @brief generateTableSuffix, 生成信号表、值表名称后缀（格式：xxxnn_yyyyMMdd_n）
     * @param info
     * @return
     */
    static QString generateTableSuffix(const JFileNameInfo &info);

    /**
     * @brief generateSignalTableName
     * @param info
     * @return
     */
    static QString generateSignalTableName(const JFileNameInfo &info);

    /**
     * @brief generateRecordTableName
     * @param info
     * @return
     */
    static QString generateRecordTableName(const JFileNameInfo &info);

    /**
     * @brief generateHotSpotTableName
     * @param info
     * @return
     */
    static QString generateHotSpotTableName(const JFileNameInfo &info);

    /**
     * @brief baseLineTableName
     * @return
     */
    static QString baseLineTableName();

    /**
     * @brief createBaseLineTable
     * @return
     */
    bool createBaseLineTable();

    ///////////////account////////////////////

    /**
     * @brief accountTableName
     * @return
     */
    QString accountTableName() const;

    /**
     * @brief createAccountTable
     * @return
     */
    bool createAccountTable();

    /**
     * @brief allUserName
     * @return
     */
    QStringList allUserName() const;

    /**
     * @brief readAllUser
     * @param infos
     * @return
     */
    bool readAllUser(QList<JAccountInfo> &infos) const;

    /**
     * @brief readAllUser
     * @param infos
     * @param type
     * @return
     */
    bool readAllUser(QList<JAccountInfo> &infos, AccountUserType type) const;

    /**
     * @brief existsUser
     * @param userName
     * @return
     */
    bool existsUser(const QString &userName) const;

    /**
     * @brief checkUserName
     * @param userName
     * @param password
     * @return
     */
    bool checkUserName(const QString &userName, const QString &password) const;

    /**
     * @brief userType
     * @param userName
     * @return
     */
    AccountUserType userType(const QString &userName) const;

    /**
     * @brief setUserType
     * @param userName
     * @param type
     */
    bool setUserType(const QString &userName, AccountUserType type);

    /**
     * @brief addUser
     * @param info
     * @return
     */
    bool addUser(const JAccountInfo &info);

    /**
     * @brief removeUser
     * @param userName
     * @return
     */
    bool removeUser(const QString &userName);

    /**
     * @brief clearUser
     * @return
     */
    bool clearUser();

    /**
     * @brief userSecurity
     * @param userName
     * @return
     */
    unsigned int userSecurity(const QString &userName) const;

    /**
     * @brief setUserSecurity
     * @param userName
     * @param security
     * @return
     */
    bool setUserSecurity(const QString &userName, unsigned int security);

    ///////////////account////////////////////

private:
    JSqlTableMgr();
    ~JSqlTableMgr();

    friend class JSqlDataMgr;
    QSqlDatabase database() const;

private:
    J_DECLARE_PRIVATE(JSqlTableMgr)
    J_DECLARE_SINGLE_INSTANCE(JSqlTableMgr)
};

#endif // JSQLTABLEMGR_H
